package hk.polyu.dds;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Vector;

import android.content.*;
import android.hardware.Sensor;
import android.os.*;
import android.util.Log;


/**
 * This class implement cached data logging on one machine.
 * Once the buffer is full, the data will be flushed to the disk.
 * 
 * The data logging format is organized as follows:
 * 1. Each sensing data is placed into a new folder named as sample starting time: "yyyy.MM.dd.HH.mm.ss"
 * 2. File are named with 'SensorType_DeviceName.txt'. SensorType can be 'acc', 'gyro' and 'loc'.
 * 3. Accelerometer and Gyroscope file content is organized as: time, x, y, z.
 * 4. Location file is organized as: time, longitude, latitude, 
 * 
 * @author hezongjian
 *
 */
public class Logger {
	
	private String 		mPath = null;
	private Context 	mCx = null;	
	
	HashMap<String, Vector<BufferedWriter>>		mWriter;

	String [] 			mDevList;
	
	BufferedWriter		mLocWriter;

	
	/**
	 * Constructor of the logger
	 * @param cx			The context
	 * @param smpDate		Sample date, used as folder name.
	 * @param devList		Device list, Each device contain two files.
	 * @throws Exception
	 */
	public Logger(Context cx, Date smpDate, String [] devList) throws Exception{
		mCx = cx;
		
		// create folder.
		String state = Environment.getExternalStorageState();
		
		if (! Environment.MEDIA_MOUNTED.equals(state))
			throw new Exception("External Storage Required") ;
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
		String dateString = sdf.format(smpDate);
		
		File file = new File(mCx.getExternalFilesDir(null), dateString);
		if (!file.exists()) {
	        if (!file.mkdirs()) {
	            Log.e("polyu", "Problem creating folder");
	            throw new Exception("Problem creating folder") ;
	        }
	    }
		
		// set the full path.
		this.mPath = file.getAbsolutePath();
		mDevList = devList;
		
		mWriter = new HashMap<String, Vector<BufferedWriter>>();
	}
	
	
	public void open() throws Exception
	{
		// construct internal data structure
		for(String dev : this.mDevList) {
			Vector<BufferedWriter> vbw = new Vector<BufferedWriter>(2);
			
			File fAcc = new File(this.mPath, String.format("%s_%s.txt", dev, "acc"));
			File fGyro = new File(this.mPath, String.format("%s_%s.txt", dev, "gyro"));
			
			BufferedWriter bAcc = new BufferedWriter(new FileWriter(fAcc), 1024 * 8);
			BufferedWriter bGyro = new BufferedWriter(new FileWriter(fGyro), 1024 * 8);
			
			vbw.add(0, bAcc);
			vbw.add(1, bGyro);
			
			this.mWriter.put(dev, vbw);
		}
		
		// append the GPS.
		File fGPS = new File(this.mPath, String.format("%s_%s.txt", "localhost", "gps"));
		mLocWriter = new BufferedWriter(new FileWriter(fGPS), 1024 * 8);
		
	}
	
	public void close() throws Exception {

		for(String dev : this.mDevList) {
			for(BufferedWriter bw : this.mWriter.get(dev)) {
				bw.close();
			}
		}
		mLocWriter.close();
	}
	
	
	public void append(String dev, int type, String line) {
		line += "\r\n";
		Vector<BufferedWriter> vbw = this.mWriter.get(dev);
		
		try {
			switch (type) {
			case Sensor.TYPE_ACCELEROMETER:
				vbw.get(0).write(line);
				break;
			case Sensor.TYPE_GYROSCOPE:
				vbw.get(1).write(line);
				break;
			case 0:	// GPS
				mLocWriter.write(line);
				break;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	public void append(String dev, int type, float [] data) {
		// change the time to server time.
		long tm = System.currentTimeMillis();
		tm -= DataClient.mTimeDiff;
		
		String opt = String.format("%d, %+.8f, %+.8f, %+.8f, %+.8f", tm, data[0], data[1], data[2], data[3]);
		this.append(dev, type, opt);
	}
}
